/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or (at
 * your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 * */

// AmzServer - Tototoy's server model.
// Author: tonyjobmails@gmail.com (tonyhack).
//
// Define class Thread.
//
// Thread is a simple wrapper of pthread.
//

#ifndef __THREAD__H
#define __THREAD__H

#include <string>

#include <pthread.h>

#include "mutex.h"
#include "condition_variable.h"
#include "common.h"
#include "time_tick.h"

namespace amz {

// Defined in mutex.h
class Mutex;
// Defined in condition_variable.h
class ConditionVariable;

// State of thread.
enum ThreadState {
  THREAD_STATE_CREATE = 0,
  THREAD_STATE_ALIVE,
  THREAD_STATE_TERMINAL,
};

class Thread {
 public:
  Thread(std::string name, bool joinable = true);
  virtual ~Thread();

  inline std::string GetName() const { return this->name_; }
  
  // Let thread sleep.
  static void Sleep(uint32 msec);
  
  // Check state.
  inline bool CheckJoinable() const { return this->joinable_; }
  inline bool CheckAlive() const { return this->state_ == THREAD_STATE_ALIVE; }
  inline bool CheckTerminal() const { return this->state_ == THREAD_STATE_TERMINAL; }
  
  inline void Alive();
  // Only set state value to the terminal state.
  inline void Terminal();
  
  // Let thread start running.
  bool Start();
  
  // This is the thread's running method.
  static void *ThreadFunction(void *argument);
  
  // Every derive-class should implements this method.
  virtual void Run() = 0;
  
  // Wait for thread stopping.
  void Join();
  
 private:
  std::string name_;
  pthread_t id_;
  uint8 state_;
  // Check need pthread_join().
  bool joinable_;
  
  Mutex mutex_;
  ConditionVariable condition_variable_;

  TimeTick time_;
};

}  // namespace amz

#endif  // __THREAD__H

